﻿using System;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Net;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace restful.net.TestClient
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
            cbxMethod.SelectedItem = "GET";
        }

        private void btnGo_Click(object sender, EventArgs e)
        {
            RequestProperties prop = new RequestProperties();
            prop.Method = (string)cbxMethod.SelectedItem;
            if ((string)cbxMethod.SelectedItem == "POST" || (string)cbxMethod.SelectedItem == "PUT")
            {
                prop.Request = tbxRequestBody.Text;
            }
            string[] headers = tbxRequestHeaders.Text.Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);
            foreach (string header in headers)
            {
                string[] headerParts = header.Split(new[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
                prop.Headers.Add(headerParts[0], headerParts[1]);
            }
            prop.ContentType = (string)cbxContentType.SelectedItem;
            prop.Url = tbxResource.Text;
            prop.UserName = tbxUsername.Text;
            prop.Password = tbxPassword.Text;

            ThreadPool.QueueUserWorkItem(DoRequest, prop);
        }

        private void DoRequest(object obj)
        {
            try
            {
                Stopwatch watch = new Stopwatch();
                RequestProperties prop = (RequestProperties)obj;
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(tbxResource.Text);
                request.Method = prop.Method;
                request.Accept = prop.ContentType;
                foreach (string key in prop.Headers.AllKeys)
                {
                    request.Headers.Add(key, prop.Headers[key]);
                }
                if (!string.IsNullOrWhiteSpace(prop.UserName))
                {
                    byte[] auth = Encoding.UTF8.GetBytes(string.Format("{0}:{1}", prop.UserName, prop.Password));
                    request.Headers.Add("Authorization", "basic " + Convert.ToBase64String(auth));
                }
                watch.Start();
                if (request.Method == "POST" || request.Method == "PUT")
                {
                    byte[] bytes = Encoding.UTF8.GetBytes(prop.Request);
                    request.ContentType = prop.ContentType;
                    request.ContentLength = bytes.Length;
                    using (Stream requestStream = request.GetRequestStream())
                    {
                        requestStream.Write(bytes, 0, bytes.Length);
                    }
                }

                using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
                {

                    StringBuilder headers = new StringBuilder();
                    headers.AppendLine("HTTP/" + response.ProtocolVersion + " " + response.StatusCode);
                    foreach (string key in response.Headers.AllKeys)
                    {
                        headers.AppendLine(key + ":" + response.Headers[key]);
                    }

                    BeginInvoke(new TextSetterDelegate(SetHeaders), headers.ToString());
                    using (Stream responseStream = response.GetResponseStream())
                    {
                        using (StreamReader sr = new StreamReader(responseStream, Encoding.UTF8))
                        {
                            string responseText = sr.ReadToEnd();
                            watch.Stop();
                            BeginInvoke(new TextSetterDelegate(SetText), responseText);

                            BeginInvoke(new TextSetterDelegate(SetTime), Convert.ToString((double)watch.ElapsedTicks / TimeSpan.TicksPerMillisecond, CultureInfo.CurrentUICulture));
                        }
                    }

                }
            }
            catch (WebException we)
            {
                if (we.Response != null)
                {
                    using (HttpWebResponse response = (HttpWebResponse)we.Response)
                    {
                        StringBuilder headers = new StringBuilder();
                        headers.AppendLine("HTTP/" + response.ProtocolVersion + " " + response.StatusCode);
                        foreach (string key in response.Headers.AllKeys)
                        {
                            headers.AppendLine(key + ":" + response.Headers[key]);
                        }
                        BeginInvoke(new TextSetterDelegate(SetHeaders), headers.ToString());
                        using (Stream responseStream = response.GetResponseStream())
                        {
                            using (StreamReader sr = new StreamReader(responseStream, Encoding.UTF8))
                            {
                                string responseText = sr.ReadToEnd();

                                BeginInvoke(new TextSetterDelegate(SetText), responseText);

                            }
                        }

                    }
                }
                else
                {
                    BeginInvoke(new TextSetterDelegate(SetText), we.ToString());
                }
            }
            catch (Exception e)
            {

                BeginInvoke(new TextSetterDelegate(SetText), e.ToString());
            }
        }

        delegate void TextSetterDelegate(string text);

        private void SetTime(string text)
        {
            tbxResponseTime.Text = text;
        }

        private void SetText(string text)
        {
            tbxResponseBody.Text = text;
        }
        private void SetHeaders(string text)
        {
            tbxResponseHeaders.Text = text;
        }
    }
}
